到目前為止,我們已經完成了一個「有結構、有樣式」的履歷網站:
但這個網站目前是「靜態」的,使用者只能看,沒辦法互動。
今天開始,我們會引入 TypeScript,讓網站能有簡單的互動功能。這樣,履歷網站就會從「一份漂亮的靜態簡報」變成「有生命的應用」。
TypeScript(TS)是 JavaScript 的超集,它的最大特色就是 靜態型別。
JavaScript 允許你這樣寫:
let age = 25;
age = "三十"; // 不會報錯
在小專案也許沒差,但在大型專案裡,這種隱性錯誤會很致命。
而 TypeScript 會在你寫程式的時候就報錯:
let age: number = 25;
age = "三十"; // ❌ 報錯:不能把字串賦值給 number
這樣就能避免很多低級錯誤。
我們要在履歷網站加上一個 「更多介紹」按鈕,點下去會展開一段隱藏的內容。
<section id="about">
<h2>關於我</h2>
<img src="me.jpg" alt="我的照片" width="200">
<p>嗨,我是 Chiayu,一名前端工程師,專注於 Angular、TypeScript 與前端架構設計。</p>
<blockquote>「持續學習,讓自己比昨天更強。」</blockquote>
<!-- 隱藏的內容 -->
<p id="more-info" style="display:none;">
我有後端與雲端開發經驗,曾參與金融科技與電商專案,也熱愛分享技術文章。
</p>
<!-- 觸發按鈕 -->
<button id="toggle-btn">更多介紹</button>
</section>
main.ts
// 定義按鈕與段落元素
const toggleBtn = document.querySelector<HTMLButtonElement>('#toggle-btn');
const moreInfo = document.querySelector<HTMLParagraphElement>('#more-info');
// 確保元素存在再綁定事件
if (toggleBtn && moreInfo) {
toggleBtn.addEventListener('click', () => {
if (moreInfo.style.display === 'none') {
moreInfo.style.display = 'block';
toggleBtn.textContent = '收起介紹';
} else {
moreInfo.style.display = 'none';
toggleBtn.textContent = '更多介紹';
}
});
}
因為瀏覽器不直接執行 TS,我們需要編譯:
tsc main.ts --target ES6 --outFile main.js
在 index.html
引入 main.js
:
<script src="main.js"></script>
這就是第一個「互動功能」!雖然簡單,但代表你的履歷網站已經不再是死板的 HTML + CSS,而是能和使用者互動。
初學者常直接寫:
document.querySelector('#btn').addEventListener('click', () => {
console.log('clicked');
});
👉 問題:如果 #btn
沒有出現在頁面上,會直接報錯。
正確做法:
const btn = document.querySelector<HTMLButtonElement>('#btn');
if (btn) {
btn.addEventListener('click', () => console.log('clicked'));
}
在 TS 裡,很多人會偷懶不寫型別:
const btn = document.querySelector('#btn');
👉 問題:這樣 btn
的型別會是 Element | null
,使用時要不斷轉型,很容易出錯。
正確做法:
const btn = document.querySelector<HTMLButtonElement>('#btn');
直接指定型別,程式碼更安全。
innerHTML
修改內容很多人會用 innerHTML
來改內容:
btn.innerHTML = "<b>更多介紹</b>";
👉 問題:這樣可能造成 XSS 安全漏洞,也不必要。
正確做法:
btn.textContent = "更多介紹";
明天,我們要進一步學習 DOM 操作與事件綁定: